import { defineStore, storeToRefs } from 'pinia'
import getFormConfigStore from './formConfig'
import getModelStore from './modelStore'
import api from '@/api'
import { useFileStore } from './files'
import { useIndicatorStore } from './indicators'
import { toRaw } from 'vue'

export const useSaleFileConfigStore = getFormConfigStore('saleFiles')
export const useSaleFileStore = defineStore('saleFiles', {
  state: () => ({
    loading: true,
    error: false,
    // Liste des templates dans le cas de l'affaire courante
    templates: [],
    projectId: null,
    businessId: null,
    taskId: null,
    tree: [],
    nodesById: {},
    item: {},
    currentFile: {},
  }),
  actions: {
    setContext(projectId, businessId, taskId) {
      this.projectId = projectId;
      this.businessId = businessId;
      this.taskId = taskId;
    },
    loadTaskTree: async function () {
      const fileStore = useFileStore()
      const indicatorStore = useIndicatorStore()
      this.loading = true
      this.tree = await api.projects.getTree(this.projectId, this.businessId, this.taskId)
      this.nodesById[this.projectId] = this.tree
      this.tree.estimations.forEach((node) => {
        this.nodesById[node.id] = node
      })
      this.tree.invoices.forEach((node) => {
        this.nodesById[node.id] = node
      })
      this.tree.businesses.forEach((business) => {
        this.nodesById[business.id] = business
        business.estimations.forEach((node) => {
          this.nodesById[node.id] = node
        })
        business.invoices.forEach((node) => {
          this.nodesById[node.id] = node
        })
      })
      const allIds = Object.keys(this.nodesById)
      await fileStore.loadFromNodes(allIds)
      await indicatorStore.loadFromNodes(allIds)

      this.loading = false
    },
    loadBusinessTemplates: async function (businessId) {
      this.templates = await api.businesses.loadTemplates(businessId)
    },
    openNode: async function (node) {
      await fileStore.loadFromNode(node.id)
      await indicatorStore.loadFromNode(node.id)
    },
    addFile: async function (fileData) {
      const parentId = fileData.get('parent_id')
      const indicatorId = fileData.get('indicator_id')
      const fileTypeId = fileData.get('file_type_id')
      const fileStore = useFileStore()
      const indicatorStore = useIndicatorStore()
      const { error: fileError, current: currentFile } = storeToRefs(fileStore)
      this.loading = true
      await fileStore.addFile(fileData)

      if (!!currentFile.value) {
        this.currentFile = currentFile.value
        if (indicatorId) {
          await indicatorStore.loadItem(indicatorId)
        } else {
          await indicatorStore.loadFromNode(this.currentFile.parent_id)
          // FIXME : Il doit y avoir une bonne raison de faire ça
          // à tester si on l'enlève et mettre un commentaire si effectivement
          // ça a une réelle utilité
          if (!fileTypeId) {
            await fileStore.loadFromNode(this.currentFile.parent_id)
          }
          if (parentId && parentId !== this.currentFile.parent_id) {
            await indicatorStore.loadFromNode(parentId)
          }
        }

        this.error = null
      } else {
        this.error = fileError.value
      }

      this.loading = false
    },
    addMultipleFiles: async function (files, parentId) {
      this.loading = true
      const fileStore = useFileStore()
      const { error: fileError } = storeToRefs(fileStore)
      // On construit des formData pour l'envoi à l'api
      const formData = files.map((file) => {
        const res = new FormData()
        res.append('upload', file.file)
        res.append('description', file.file.name)
        res.append('parent_id', parentId)
        return res
      })
      await fileStore.addMultipleFiles(formData)
      if (!!fileError.value) {
        this.error = fileError.value
      } else {
        this.error = null
      }
      this.loading = false
    },
    updateFile: async function (fileData, fileId, originalParentId) {
      const indicatorId = fileData.get('indicator_id')

      const fileStore = useFileStore()
      const indicatorStore = useIndicatorStore()

      const { error: fileError, current: currentFile } = storeToRefs(fileStore)
      this.loading = true
      await fileStore.updateFile(fileData, fileId)

      if (!!currentFile.value) {
        this.currentFile = currentFile.value
        if (indicatorId) {
          await indicatorStore.loadItem(indicatorId)
        } else {
          await indicatorStore.loadFromNode(this.currentFile.parent_id)
        }
        if (
          originalParentId &&
          originalParentId !== this.currentFile.parent_id
        ) {
          await indicatorStore.loadFromNode(originalParentId)
        }
        this.error = null
      } else {
        this.error = fileError.value
      }

      this.loading = false
    },
    deleteFile: async function (file, node, indicator) {
      const fileStore = useFileStore()
      const indicatorStore = useIndicatorStore()

      const { error: fileError } = storeToRefs(fileStore)
      this.loading = true
      await fileStore.deleteFile(file.id)

      if (!fileError.value) {
        if (indicator) {
          await indicatorStore.loadItem(indicator.id)
        }
        this.error = null
      } else {
        this.error = fileError.value
      }

      this.loading = false
    },
    downloadFile: async function (fileId) {
      const fileStore = useFileStore()
      fileStore.downloadFile(fileId)
    },
    template: async function (node, file_requirement, task_context) {
      let bid = node.business_id
      if (node.type_ === 'business') {
        bid = node.id
      }
      let param_context = ''
      if(task_context && task_context!="0") {
        param_context = '&task=' + task_context
      }
      window.open(
        `/businesses/${bid}/py3o?file=${file_requirement.file_type_id}${param_context}`
      )
    },
    downloadAll: async function () {
      window.open(`/projects/${this.projectId}/files.zip`)
    },
    moveFile: async function (file, parentId) {
      const fileStore = useFileStore()
      const indicatorStore = useIndicatorStore()

      const previousNodeId = file.parent_id
      const { error: fileError } = storeToRefs(fileStore)
      this.loading = true
      await fileStore.moveFile(file.id, parentId)
      if (!fileError.value) {
        await indicatorStore.loadFromNode(parentId)
        await indicatorStore.loadFromNode(previousNodeId)
        this.error = null
      } else {
        this.error = fileError.value
      }

      this.loading = false
    },
  },
  getters: {
    getFiles(state) {
      return (parentId) => {
        const fileStore = useFileStore()

        return fileStore.getByParentId(parentId)
      }
    },
    getIndicatorFiles(state) {
      return (parentId, indicatorId) => {
        const indicatored_files = this.getIndicators(parentId).map(
          (indicator) => indicator.file_id
        )
        const fileStore = useFileStore()

        const fileObject = fileStore.getByParentId(
          parentId,
          null,
          indicatored_files
        )
        return Object.fromEntries(fileObject.map((file) => [file.id, file]))
      }
    },
    getFreeFiles(state) {
      return (node) => {
        const indicatored_files = this.getIndicators(node).map(
          (indicator) => indicator.file_id
        )
        const fileStore = useFileStore()

        return fileStore.getByParentId(node.id, indicatored_files)
      }
    },
    getIndicators(state) {
      return (node, currentType = null) => {
        if (typeof node === 'number' || typeof node === 'string') {
          node = this.getNodeById(node)
        }
        // const node = this.getNodeById(nodeId)
        const indicatorStore = useIndicatorStore()
        let result = []

        if (node.type_ == 'business' || node.type_ == 'project') {
          result = indicatorStore.getByNodeId(node.id)
        } else {
          result = indicatorStore.getByNodeId(node.id, [
            'mandatory',
            'optionnal',
            'recomended',
          ])
        }
        if (currentType != null) {
          result.push(indicatorStore.getByTypeId(currentType))
        }
        console.log('Retrieving indicators for node', node.id)
        console.log(result)
        return result
      }
    },
    getIndicatorsByBusinessId(state) {
      return (businessId) => {
        const tasks = toRaw(this.getBusinessTasks(businessId))

        const indicatorStore = useIndicatorStore()
        // Pour toutes les tasks on va récupérer les indicators dans un array result
        let result = {}
        tasks.forEach((task) => {
          task = toRaw(task)
          const taskIndicators = indicatorStore.getByNodeId(task.id, [
            'business_mandatory',
          ])
          // évite d'avoir le même fichier plusieurs fois
          // (Plusieurs factures ont un requirement au niveau de l'affaire
          // pour le même type de fichier, on ne veut l'afficher qu'une
          // fois au niveau de l'affaire elle-même)
          taskIndicators.map((indicator) => {
            if (!result[indicator.file_type_id]) {
              result[indicator.file_type_id] = indicator
            }
          })
        })
        return Object.values(result)
      }
    },
    getIndicatorsByProjectId(state) {
      return (projectId) => {
        const nodes = state.tree
        const indicatorStore = useIndicatorStore()
        let result = []
        nodes.forEach((node) => {
          result = result.concat(
            indicatorStore.getByNodeId(node.id, ['project_mandatory'])
          )
        })
        return result
      }
    },
    getBusinessTasks(state) {
      return (businessId) => {
        return this.tree.filter((node) => node.business_id === businessId)
      }
    },
    getNodeById(state) {
      return (nodeId) => {
        return toRaw(state.nodesById)[parseInt(nodeId)]
      }
    },
  },
})
